import tushare as ts
import talib as ta
import baostock as bs
import datetime
import numpy as np
import copy
import go1


'''
code：股票代码，即6位数字代码，或者指数代码（sh=上证指数 sz=深圳成指 hs300=沪深300指数 sz50=上证50 zxb=中小板 cyb=创业板）
start：开始日期，格式YYYY-MM-DD
end：结束日期，格式YYYY-MM-DD
ktype：数据类型，D=日k线 W=周 M=月 5=5分钟 15=15分钟 30=30分钟 60=60分钟，默认为D
retry_count：当网络异常后重试次数，默认为3
pause:重试时停顿秒数，默认为0
ts.get_hist_data('600848', ktype='W') #获取周k线数据
ts.get_hist_data('600848', ktype='M') #获取月k线数据
ts.get_hist_data('600848', ktype='5') #获取5分钟k线数据
ts.get_hist_data('600848', ktype='15') #获取15分钟k线数据
ts.get_hist_data('600848', ktype='30') #获取30分钟k线数据
ts.get_hist_data('600848', ktype='60') #获取60分钟k线数据
ts.get_hist_data('sh'）#获取上证指数k线数据，其它参数与个股一致，下同
ts.get_hist_data('sz'）#获取深圳成指k线数据
ts.get_hist_data('hs300'）#获取沪深300指数k线数据
ts.get_hist_data('sz50'）#获取上证50指数k线数据
ts.get_hist_data('zxb'）#获取中小板指数k线数据
ts.get_hist_data('cyb'）#获取创业板指数k线数据
'''



#pro = ts.pro_api(token='c33acb7493eac4affba5d8b9b79bf3ac34f2d6125ceb1fc9ae93273b')
'''
#df = pro.daily(ts_code='603138.SH', start_date='20190501', end_date='20190814')
df = ts.get_hist_data('600848',ktype='30')
print(df)
d2 = [[df.iloc[i,2],df.iloc[i,5],df.iloc[i,4],df.iloc[i,3]] for i in range(df.shape[0])]
print(d2[0])

ta.set_compatibility(1)

dif,dea,macd = ta.MACD(df.close.values,12,26,9)
print(macd.tolist())
'''
def list_replace(l,ele,new_ele):
    for i in range(len(l)):
        if l[i]==ele:
            l[i] = new_ele
    return l



#map a list with some non-zero elements and zero elements
#to a new list
#whose elements between two non-zero elements is well-distributed
#common difference d:(an - am)/(n-m+1)
def linear_map(l):
    i1 = np.argmax(np.array(l)>0)
    i2 = i1+1
    l_new = copy.copy(l)
    length = len(l)
    if l_new[-1]==0:
        for x in range(length):
            if l_new[length-1-x] == 0:
                continue
            else:
                l_new[(length-1-x):] = [l_new[length-1-x]]*(x+1)
                break


    while(i2<length):


        if l[i2] == 0:
            i2 += 1
            continue
        else:
            d = (l[i2] - l[i1])/(i2-i1)
            for i in range(i1+1,i2):
                l_new[i] = round(l[i1] +(i-i1)*d,4)
            i1 = i2
            i2 += 1
            #print(i1, i2,l[i1],l[i2],sep=',')
    return l_new


#get the max value list or min value list
def get_max_list(s,n=3):
    #l must is a k list
    #2:min 3:max
    l_new = [s[i][n] for i in range(len(s)) ]
    return l_new

#list copy and copy reduce a element and return new list
def reduce(l,x):
    #function:extract list method
    #[1,2,3]-3 = [1,2]
    #[1,2,3,3]-3 = [1,2]
    l_new = copy.copy(l)
    for i in l_new:
        if i == x:
            l_new.remove(x)
    return l_new

def drop(l,i):
    l1 = l[0:i]
    l2 = l[i+1:]
    lc = l1+l2
    return lc

def search_delta(i,l_another):
    for j in range(len(l_another)):
        if l_another[j] - i>3:
            return j
    return -1


def judge_breakdown(former_value,index,catted_list,method=0,limit=8):
    #击穿：三根k收盘价均高于（低于）对应点
    #比较高点时，第三根及以后包含一根阳线
    #比较低点时，第三根及以后包含一根阴线
    #method:0 此时比较低点
    #method:1 此时比较高点
    method = method
    #todo: try to use the un-catted list
    #todo: consider about this condition: 1.there are over three k
    #todo: which satisfy, but if the k bigger than four is unsatisfied, in the
    #todo: same time, it is a yang, how to solve it?
    catted_list = catted_list
    close_list = [float(i[1]) for i in catted_list]
    try:
        if method:

            if former_value <= min(close_list[index:index+3]):
                for j in range(index+2,index+limit):
                    #v3 = [catted_list[j][1],catted_list[j][0]]
                    if catted_list[j][1]>catted_list[j][0]:
                        return True

        else:

            if former_value >= max(close_list[index:index+3]):
                #v1 = former_value
                #v2 = max(close_list[index:index + 3])
                for j in range(index+2,index+limit):
                    if catted_list[j][1]<catted_list[j][0]:
                        return True

        return False
    except Exception as e:
        print('error',e)
        return False

def  mix_value_date(vl,datel):
    l = [[i[1],i[0]] for i in zip(vl,datel)]
    return l


def judge_extreme(v,i,j,l,method=max):
    #method:max,min--->function
    #print(v,i,j,l,sep=';')
    if v==method(l[i:j+1]):
        return False
    else:
        return i+l[i:].index(method(l[i:j+1]))




class stock_info:
    def __init__(self,id,interval_month = 1,start = '2018-06-01'):
        bs.login()
        self.id = id
        self.now = str(datetime.datetime.now().year)+"-"+str(datetime.datetime.now().month)\
    +"-"+str(datetime.datetime.now().day)
        #self.start = str(datetime.datetime.now().year)+"-"+\
                     #str(datetime.datetime.now().month-interval_month)\
    #+"-"+str(datetime.datetime.now().day)
        self.start = start
        self.Kday =  bs.query_history_k_data_plus(self.id,"date,open,high,low,close"\
                                                  ,start_date=self.start,\
                                                  end_date=self.now,frequency="d").get_data()
        self.K60 = bs.query_history_k_data_plus(self.id,"date,open,high,low,close"\
                                                  ,start_date=self.start,\
                                                  end_date=self.now,frequency='60').get_data()
        self.K30 = bs.query_history_k_data_plus(self.id, "date,open,high,low,close" \
                                                , start_date=self.start, \
                                                end_date=self.now, frequency='30').get_data()
        self.K15 = bs.query_history_k_data_plus(self.id,"date,open,high,low,close"\
                                                  ,start_date=self.start,\
                                                  end_date=self.now,frequency='15').get_data()
        self.K5 = bs.query_history_k_data_plus(self.id, "date,open,high,low,close" \
                                                , start_date=self.start, \
                                                end_date=self.now, frequency='5').get_data()
        bs.logout()

    def cat(self,k,frequecy=1):
        #todo:need test
        #5:5 minutes
        #30:30 minutes
        #60:60 minutes
        #1: day
        k_index = k.copy()
        index_l = []
        l = [[float(k_index.iloc[i][1]),float(k_index.iloc[i][4]),\
              float(k_index.iloc[i][3]),float(k_index.iloc[i][2])]\
             for i in range(k_index.shape[0])]
        if frequecy == 1:
            date_l = [k_index.iloc[i][0] for i in range(k_index.shape[0])]
        else:
            #num = 2+240/frequecy
            date_l = [k_index.iloc[i][0] +'-'+ str(i) for i in range(k_index.shape[0])]
        origin_date = copy.copy(date_l)
        start = 5
        i = 5
        length = len(l)
        counter = 0
        temp = -1

        while(i<length-1):
            #i includes i+1

            if (l[i][2]<=l[i+1][2] and l[i][3]>l[i+1][3]) or \
                    (l[i][2]>=l[i+1][2] and l[i][3]<l[i+1][3]):

                if (l[i-1][2]<=l[i][2] and l[i-1][3]<=l[i][3]):
                #up trend get high high
                    if temp<0:
                        temp = counter
                    if (l[i][3]<l[i+1][3]):
                        temp = counter+1


                    l[i][2] = max(l[i+1][2],l[i][2])
                    l[i][3] = max(l[i+1][3],l[i][3])
                    l = drop(l,i+1)
                    length -= 1
                    counter += 1
                    date_l = drop(date_l,i+1)

                elif(l[i-1][2]>=l[i][2] and l[i-1][3]>=l[i][3]):
                    #down trend low low
                    if temp<0:
                        temp = counter
                    if (l[i][2]>l[i+1][2]):
                        temp = counter+1


                    l[i][2] = min(l[i+1][2],l[i][2])
                    l[i][3] = min(l[i+1][3],l[i][3])
                    l = drop(l,i+1)
                    date_l = drop(date_l,i+1)
                    length -= 1
                    counter += 1
                else:
                    start -= 1
                    i -= 1
                    #counter -= 1
                    if i<0:
                        print('notice! all the predata is used but still include')
                        break
            else:
                if temp<0:
                    temp = counter
                index_l.append(temp)
                i += 1
                counter += 1
                #l:[[open,close,min,max]...]
                temp = -1
        index_l.append(counter)

        return [l[start:],date_l[start:],index_l,origin_date[start:],start]

    def MACD(self,k):
        #todo: need test
        #bs.login()

        #print(self.Kday.shape)
        #bs.logout()
        ta.set_compatibility(1)
        data = np.array([float(k.iloc[i][4]) for i in range(k.shape[0])],dtype=np.float)

        dif, dea, macd = ta.MACD(data, 12, 26, 9)
        macd[np.isnan(macd)] = 0
        #print(macd.shape)
        dif[np.isnan(dif)] = 0
        return list(macd*2),list(dif)

    def MACD_cat(self,catted_list):
        catted_list = catted_list[0]
        #print(catted_list)
        data = np.array([catted_list[i][1] for i in range(len(catted_list))], dtype=np.float)
        dif, dea, macd = ta.MACD(data, 12, 26, 9)
        macd[np.isnan(macd)] = 0
        dif[np.isnan(dif)] = 0
        #print(macd)
        #todo: 验证此处 是否可行
        return list(2*macd),list(dif)

    def get_start_by_threshold(self,catted_k,threshold=9):
        k = catted_k[0][0:threshold]

        l_ava = [(i[2]+i[3])/2 for i in k]
        xyb = sum([l_ava[i]*i for i in range(threshold)])/threshold
        xbyb = sum([i for i in range(threshold)])/threshold*sum(l_ava)/threshold
        x2b = sum([i*i for i in range(threshold)])/threshold
        xb2 = sum([i for i in range(threshold)])**2/threshold/threshold
        kl = (xyb-xbyb)/(x2b-xb2)
        #print('k:',kl)
        flag = 0
        min_l = [i[2] for i in k]
        max_l = [i[3] for i in k]
        if kl>=0:
            flag = 1
            #start min
            start = min_l.index(min(min_l))
        else:
            start = max_l.index(max(max_l))
        return flag,start


    def strict_stroke(self,catted_list):
        #todo:need test
        l = catted_list[0]
        date_l = catted_list[1]
        origin_date = catted_list[3]
        index_l = catted_list[2]
        #先将所有高低点的索引得到
        #针对第一个高（低）点寻找下一个低（高）点
        #若二者索引的差大于等于4 寻找下一个高（低）点
        #若在此期间发现更低（高）点，则将新点更新为端点
        #若找到下一个高点，且此期间无更低点且无更高点，且下一个高点的索引与最低点索引
        #相差大于等于4，则此笔可成
        #否则，如有更高点，需将
        new_l = [0]*len(l)
        max_l = []
        min_l = []
        for i in range(1,len(l)-1):
            if i==1 and l[i-1][-1]>l[i][-1] and l[i-1][-1]>l[i+1][-1]:
                max_l.append(0)
            if i==1 and l[i-1][-1]<l[i][-1] and l[i-1][-1]<l[i+1][-1]:
                min_l.append(0)
            if l[i][-1]>l[i-1][-1] and l[i][-1]>l[i+1][-1]:
                max_l.append(i)
            if l[i][-2]<l[i-1][-2] and l[i][-2]<l[i+1][-2]:
                min_l.append(i)
        if l[-1][-1]>l[-2][-1]:
            max_l.append(len(l)-1)
        if l[-1][-2]<l[-2][-2]:
            min_l.append(len(l)-1)

        #input()
        #if max_l[0]<= min_l[0]:
        if not self.get_start_by_threshold(catted_list)[0]:
            extreme_index = self.get_start_by_threshold(catted_list)[1]
            l_another = min_l
            flag = 1
            method = min
        else:
            extreme_index = self.get_start_by_threshold(catted_list)[1]
            l_another = max_l
            flag = 0
            method = max
        next_extreme = l_another[search_delta(extreme_index, l_another)]
        index_of_next = l_another.index(next_extreme)
        if flag:
            l_another = max_l
            method = min
        else:
            l_another = min_l
            method = max
        next_extreme2 = l_another[search_delta(next_extreme, l_another)]
        index_of_next2 = l_another.index(next_extreme2)
        criterion = 0
        criterion2 = 0
        test = 0

        while(search_delta(l[extreme_index][flag+2],l_another)>0):
            if search_delta(next_extreme, l_another)<0:
                if flag:
                    new_l[extreme_index] = l[extreme_index][3]
                    new_l[next_extreme] = l[next_extreme][2]
                    #new_l[max_l[-1]] = l[max_l[-1]][3]
                else:
                    new_l[extreme_index] = l[extreme_index][2]
                    new_l[next_extreme] = l[next_extreme][3]
                    #new_l[min_l[-1]] = l[min_l[-1]][2]

                break

            #input('next')
            criterion = judge_extreme(l[next_extreme][3-flag],extreme_index,next_extreme2,get_max_list(l,3-flag),method)
            test = reduce([max,min],method)[0]
            criterion2 = judge_extreme(l[next_extreme2][2+flag],next_extreme,next_extreme2,\
                                       get_max_list(l,2+flag),reduce([max,min],method)[0])


            if criterion:
                #print('not a extreme this point')
                #当极点不是next_extreme时，把索引更新成极点坐标
                #更新后，重新寻找next_extreme2
                #再次进行判断
                if criterion>next_extreme:
                    next_extreme = criterion
                    if search_delta(next_extreme, l_another) < 0:
                        if flag:
                            new_l[extreme_index] = l[extreme_index][3]
                            new_l[next_extreme] = l[next_extreme][2]
                            #new_l[max_l[-1]] = l[max_l[-1]][3]
                        else:
                            new_l[extreme_index] = l[extreme_index][2]
                            new_l[next_extreme] = l[next_extreme][3]
                            #new_l[min_l[-1]] = l[min_l[-1]][2]
                        break
                    next_extreme2 = l_another[search_delta(next_extreme, l_another)]
                    index_of_next2 = l_another.index(next_extreme2)
                    continue
                else:
                    #虽然有极点，但极点在前，且不满足5根K线的要求
                    #此时，应将next_extreme更新为当前next_extreme的下一个index
                    l_temp = reduce([max_l,min_l],l_another)[0]
                    next_extreme = l_temp[index_of_next+1]
                    index_of_next += 1
                    if search_delta(next_extreme, l_another) < 0:
                        if flag:
                            new_l[extreme_index] = l[extreme_index][3]
                            new_l[next_extreme] = l[next_extreme][2]
                            #new_l[max_l[-1]] = l[max_l[-1]][3]
                        else:
                            new_l[extreme_index] = l[extreme_index][2]
                            new_l[next_extreme] = l[next_extreme][3]
                            #new_l[min_l[-1]] = l[min_l[-1]][2]
                        break
                    next_extreme2 = l_another[search_delta(next_extreme, l_another)]
                    index_of_next2 = l_another.index(next_extreme2)
                    continue

            else:
                if criterion2:
                    try:
                        next_extreme2 = l_another[index_of_next2+1]
                        index_of_next2 += 1
                    except:
                        #print('ex')
                        new_l[-1] = l[-1][1]
                        break
                    continue
                else:
                    if flag:
                        new_l[extreme_index] = l[extreme_index][3]
                        new_l[next_extreme] = l[next_extreme][2]
                        flag = 0
                        extreme_index = next_extreme
                        l_another = max_l
                        method = max

                    else:
                        new_l[extreme_index] = l[extreme_index][2]
                        new_l[next_extreme] = l[next_extreme][3]
                        flag = 1
                        extreme_index = next_extreme
                        l_another = min_l
                        method = min

                    next_extreme = l_another[search_delta(extreme_index, l_another)]
                    index_of_next = l_another.index(next_extreme)
                    l_another = reduce([max_l,min_l],l_another)[0]
                    if search_delta(next_extreme, l_another) < 0:
                        if flag:
                            new_l[extreme_index] = l[extreme_index][3]
                            new_l[next_extreme] = l[next_extreme][2]
                            #new_l[max_l[-1]] = l[max_l[-1]][3]
                        else:
                            new_l[extreme_index] = l[extreme_index][2]
                            new_l[next_extreme] = l[next_extreme][3]
                            #new_l[min_l[-1]] = l[min_l[-1]][2]
                        break
                    next_extreme2 = l_another[search_delta(next_extreme, l_another)]
                    index_of_next2 = l_another.index(next_extreme2)

        final_l = [0]*len(origin_date)

        #print('f',len(final_l))
        for i in range(len(new_l)):
            if new_l[i]>0:

                final_l[index_l[i]] = new_l[i]

        return new_l,list_replace(linear_map(final_l),0,'-'),final_l,origin_date

    #notice:
    #1.using catted list,for we can not find the exact point where stroke ends
    #it means more sticktly
    #2.using 1+1 theory
    #不在创新高后，低点有效击穿前任低点
    #不在创新高，且前一低点击穿更前点，同时低点亦击穿更前点
    def segement(self,stroke_list,catted_list,k):
        dic = {1:'down',0:'up'}
        cat_start = catted_list[-1]
        stroke_list = stroke_list[2]
        #new_list = copy.copy(stroke_list)
        start_index = np.argmax(np.array(stroke_list)>0)
        length = len(stroke_list)
        seg_list = [0]*length
        trend_list = [0]*length
        id_list = []
        for i in range(length):
            if stroke_list[i]>0:
                id_list.append(i)

        #firstly,judge this segment's trendency
        flag =  (stroke_list[id_list[0]]<stroke_list[id_list[1]])
        if flag:
            #此时，总是先认定这一线段是上升的
            #通过判断点1是否为终结来判定假设的正确性
            v00 = stroke_list[id_list[3]]
            v01 = stroke_list[id_list[1]]
            a = judge_breakdown(stroke_list[id_list[2]],id_list[4],self.to_list(k)[2][cat_start:],0)
            if (stroke_list[id_list[3]]<stroke_list[id_list[1]]) and \
                    judge_breakdown(stroke_list[id_list[2]],id_list[4],self.to_list(k)[2][cat_start:],0):
                #此时说明趋势终结，即开始的假设是错误的
                #所以应以下降趋势为前提展开
                v1 = stroke_list[id_list[3]]
                v2 = stroke_list[id_list[1]]
                seg_list[id_list[1]] = stroke_list[id_list[1]]
                flag_down = 1
                start = 2

            else:
                #此时说明假设正确，直接展开
                seg_list[id_list[0]] = stroke_list[id_list[0]]
                flag_down = 0
                start = 3
        else:
            #假设下降
            if stroke_list[id_list[3]]>stroke_list[id_list[1]] and \
                    judge_breakdown(stroke_list[id_list[2]],id_list[4],self.to_list(k)[2][cat_start:],1):
                #此时说明趋势终结，即开始的假设是错误的
                #所以应以上升趋势为前提展开
                seg_list[id_list[1]] = stroke_list[id_list[1]]
                flag_down = 0
                start = 2

            else:
                #此时说明假设正确，直接展开
                seg_list[id_list[0]] = stroke_list[id_list[0]]
                flag_down = 1
                start = 3


        while(start+3<len(id_list)):
            if not flag_down:
                if (stroke_list[id_list[start+2]]<=stroke_list[id_list[start]]):

                    if judge_breakdown(stroke_list[id_list[start-1]],id_list[start+1],\
                                       self.to_list(k)[2][cat_start:],0):
                        if judge_breakdown(stroke_list[id_list[start-1]],id_list[start+3],\
                                           self.to_list(k)[2][cat_start:],0):
                            # 上升终结，改为下降
                            seg_list[id_list[start]] = stroke_list[id_list[start]]
                            trend_list[id_list[start]] = 'up'
                            start += 1
                            flag_down = 1
                            continue
                        else:
                            start += 2
                            continue

                    else:
                        if judge_breakdown(stroke_list[id_list[start+1]],id_list[start+3]\
                                           ,self.to_list(k)[2][cat_start:],0):
                            #上升终结，改为下降
                            seg_list[id_list[start]] = stroke_list[id_list[start]]
                            trend_list[id_list[start]] = 'up'
                            start += 1
                            flag_down = 1
                            continue
                        else:
                            start += 2
                            continue
                else:
                    start += 2
                    continue
            else:
                if (stroke_list[id_list[start+2]]>=stroke_list[id_list[start]]):

                    if judge_breakdown(stroke_list[id_list[start-1]],id_list[start+1],\
                                       self.to_list(k)[2][cat_start:],1):
                        if judge_breakdown(stroke_list[id_list[start-1]],id_list[start+3],\
                                           self.to_list(k)[2][cat_start:],1):
                            # 下降终结，改为上升
                            seg_list[id_list[start]] = stroke_list[id_list[start]]
                            trend_list[id_list[start]] = 'down'
                            start += 1
                            flag_down = 0
                            continue
                        else:
                            start += 2
                            continue

                    else:
                        if judge_breakdown(stroke_list[id_list[start+1]],id_list[start+3]\
                                           ,self.to_list(k)[2][cat_start:],1):
                            #上升终结，改为下降
                            seg_list[id_list[start]] = stroke_list[id_list[start]]
                            trend_list[id_list[start]] = 'down'
                            start += 1
                            flag_down = 0
                            continue
                        else:
                            start += 2
                            continue
                else:
                    start += 2
                    continue

        seg_list_for_scatter = mix_value_date(seg_list,catted_list[3])
        final = []
        for i in seg_list_for_scatter:
            if i[1]>0:
                final.append(i)
        return final,seg_list,trend_list




    def center(self,stroke,segment):
        #中枢：连续三笔里，低点中最高的和高点中最低的组成的区间
        #若区间不存在，则不构成中枢
        #下降趋势中，中枢由上升一笔起始
        #上升趋势中，中枢由下降一笔起始
        #已经记做中枢的笔不能参与到其他中枢里
        #未能脱离中枢的笔，作为中枢的延伸2
        #若一笔超过中枢中所有笔的最大、最小极限，认为出中枢
        seg_index = segment[1]
        #trend_list = segment[2]
        temp = stroke
        stroke = stroke[2]
        ext_l = []
        for i in range(len(stroke)):
            if stroke[i]>0:
                ext_l.append(i)

        length = len(seg_index)
        #print('seg_index',seg_index)
        start = length-1-np.argmax(np.array(seg_index)[::-1]>0)
        if start == length-1:
            start = 0
        #print('start',start)
        next_k = np.array(stroke[start+1:])
        #this means go into down trend
        len_ext = len(ext_l)
        i = 0
        cmin = cmax = -1
        c0 = c1 = -1
        center_l = []
        #flag:1 means center end 0 means center continue
        flag = 1
        if (stroke[start]>next_k[next_k>0][0]):
            while(i<len_ext):
                if ext_l[i] <=start:
                    i += 1
                    continue
                else:
                    #this way, center exists
                    if i+3<len_ext and flag:
                        if stroke[ext_l[i]]<stroke[ext_l[i+3]]:
                            cmin = max(stroke[ext_l[i]],stroke[ext_l[i+2]])
                            cmax = min(stroke[ext_l[i+1]],stroke[ext_l[i+3]])
                            c0 = ext_l[i]
                            c1 = ext_l[i+3]
                            i += 4
                            flag = 0
                            if i+1 >= len_ext:
                                center_l.append([cmin,cmax,c0,c1])
                                break
                        else:
                            #judge is in center or not
                            i += 2
                    elif i+1<len_ext and flag==0:
                        if not((stroke[ext_l[i+1]]<cmin and stroke[ext_l[i]]<cmin)\
                                or (stroke[ext_l[i+1]]>cmax and stroke[ext_l[i]]>cmax\
                                       or stroke[ext_l[i+1]]>max(stroke[ext_l[i-3]:ext_l[i+1]]))\
                                or stroke[ext_l[i+1]]<min(stroke[ext_l[i-3]:ext_l[i+1]])):

                            c1 = ext_l[i+1]
                            i += 2
                            if i+1>=len_ext:
                                center_l.append([cmin,cmax,c0,c1])
                                break

                        else:
                            flag = 1
                            center_l.append([cmin,cmax,c0,c1])
                            cmin = cmax = c0 = c1 = -1

                    elif i+3>=len_ext and flag:
                        break
                    elif i+1>=len_ext and flag==0:
                        c1 = i
                        center_l.append([cmin, cmax, c0, c1])
                        break
                    else:
                        print('????????')
                        print('warning')
                        i += 1
        #in up trend
        if (stroke[start] < next_k[next_k > 0][0]):
            while (i < len_ext):
                if ext_l[i] <= start:
                    i += 1
                    continue
                else:
                    # this way, center exists
                    if i + 3 < len_ext and flag:
                        if stroke[ext_l[i]] > stroke[ext_l[i + 3]]:
                            cmax = min(stroke[ext_l[i]], stroke[ext_l[i + 2]])
                            cmin = max(stroke[ext_l[i + 1]], stroke[ext_l[i + 3]])
                            c0 = ext_l[i]
                            c1 = ext_l[i + 3]
                            i += 4
                            flag = 0
                            if i + 1 >= len_ext:
                                center_l.append([cmin, cmax, c0, c1])
                                break
                        else:
                            # judge is in center or not
                            i += 2
                    elif i + 1 < len_ext and flag == 0:
                        if not ((stroke[ext_l[i + 1]] < cmin and stroke[ext_l[i]] < cmin)\
                                or (stroke[ext_l[i + 1]] > cmax and stroke[ext_l[i]] > cmax \
                                or stroke[ext_l[i + 1]] > max(stroke[ext_l[i - 3]:ext_l[i + 1]])) \
                                or stroke[ext_l[i + 1]] < min(stroke[ext_l[i - 3]:ext_l[i + 1]])):
                            c1 = ext_l[i + 1]
                            i += 2
                            if i + 1 >= len_ext:
                                center_l.append([cmin, cmax, c0, c1])
                                break
                        else:
                            flag = 1
                            center_l.append([cmin, cmax, c0, c1])
                            cmin = cmax = c0 = c1 = -1

                    elif i + 3 >= len_ext and flag:
                        break
                    elif i + 1 >= len_ext and flag == 0:
                        c1 = i
                        center_l.append([cmin, cmax, c0, c1])
                        break
                    else:
                        print('????????')
                        print('warning')
                        i += 1

        center_min = ['-']*center_l[-1][2]+[center_l[-1][0]]*\
                     (center_l[-1][3]-center_l[-1][2]+1)+['-']*\
                     (len(temp[-1])-center_l[-1][3]-1)
        center_max = ['-']*center_l[-1][2]+[center_l[-1][1]]*\
                     (center_l[-1][3]-center_l[-1][2]+1)+['-']*\
                     (len(temp[-1])-center_l[-1][3]-1)
        center_for_chart = [center_min,center_max]
        return center_l,center_for_chart




    def to_list(self,k):
        #convert k data to list ,for send to the berforehand
        date_list = [k.iloc[i][0] for i in range(k.shape[0])]
        #open:1 close:4 min:3 max:2
        data_list = [[float(k.iloc[i][1]),float(k.iloc[i][4]),float(k.iloc[i][3]),\
                      float(k.iloc[i][2])] for i in range(k.shape[0])]

        return [self.id,date_list,data_list]


    def second_purchase(self,stroke,center):
        try:
            center_end = center[0][-1][3]
            center_max = center[0][-1][1]
            stroke_joint = stroke[2]

            for i in stroke_joint[center_end+1:]:
                if i>center_max:
                    print('possible',self.id)
                    return True

            return False
        except:
            return False
    def strict_second_purchase(self,stroke,center):
        try:
            center_end = center[0][-1][3]
            center_max = center[0][-1][1]
            stroke_joint = stroke[2]
            flag = 0
            for i in stroke_joint[center_end + 1:]:
                if flag>=2:
                    print('strickt:',self.id)
                    return True
                if i > center_max:
                    flag += 1
            return False
        except:
            return False

    def future(self,stroke,center,segment,k):
        #先人工判断背驰
        #todo:自动判断背驰
        #todo:MACD回零

        #同级别分解后，发生了两中枢背驰
        #最后一笔的终点高于倒数第二笔
        #或最后一笔高于倒数第三笔

        stroke = stroke[0]
        stroke_nonzero = []
        for i in stroke:
            if i >0:
                stroke_nonzero.append(i)
        crite = stroke_nonzero[-1]>stroke_nonzero[-2] or\
                stroke_nonzero[-1]>stroke_nonzero[-3]


        center_l = center[0]
        try:
            c = center_l[-2][2]
        except:
            #print('center')
            return False

        try:
            k = [i[3] for i in k[-1]]
            seg_index = segment[1]
            #print('seg:',seg_index)
            #print(center_l)

            start = np.array(seg_index)[np.array(seg_index)>0][-1]
            seg_index.reverse()
            index_start = len(seg_index)-1-np.argmax(np.array(seg_index)>0)
            #print('start',start)
            #stroke_l = stroke[2]
            #print('test:', start, center_l[-2][0])
            if center_l[-2][2]>index_start and center_l[-2][0]<start and\
                    crite:
                print('test:',start,center_l[-2][0])
                return self.id
            else:
                return False
        except Exception as e:
            #print('inside')
            print(e)
            return False







if __name__ == '__main__':
    '''
    id = 'sh.600110'
    eg = stock_info(id)
    s = eg.strict_stroke(eg.cat(eg.Kday))
    #p = eg.segement(eg.strict_stroke(eg.cat(eg.Kday)),eg.cat(eg.Kday),eg.Kday)
    #datex = eg.cat(eg.K5)[1]
    #c = eg.center(eg.strict_stroke(eg.cat(eg.Kday)),p)

    '''
    
    l = go1.get_idlist()[2000:]
    f = open('possible.txt','w+')
    for i,id in enumerate(l):
        if i>600:
            break
        try:
            eg = stock_info(id)
            print('start:',eg.id)
            s = eg.strict_stroke(eg.cat(eg.Kday))
            p = eg.segement(eg.strict_stroke(eg.cat(eg.Kday)), eg.cat(eg.Kday), eg.Kday)
            k = eg.to_list(eg.Kday)
            c = eg.center(eg.strict_stroke(eg.cat(eg.Kday)), p)
            if eg.future(s,c,p,k):
                print('可能：',eg.id)
                f.write(id)
                f.write('\n')
                    #break

        except Exception as e:
            print('error:',id)
            print('error:',e)
            #break
    f.close()










